<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <title>狮子座（手敲）</title>
    <link rel="icon" href="https://img.kaikeba.com/kkb_portal_icon.ico" />
    <style>
      body {
        margin: 0;
        overflow: hidden;
      }

      #canvas {
        background-color: antiquewhite;
        background: url('./images/sky.jpg') no-repeat right bottom;
        background-size: cover;
      }
    </style>
  </head>

  <body>
    <canvas id="canvas"></canvas>
    <!-- 顶点着色器 -->
    <script id="vertexShader" type="x-shader/x-vertex">
      attribute vec4 a_Attr;
      varying float v_Alpha;
      void main(){
          gl_Position=vec4(a_Attr.x,a_Attr.y,0.0,1.0);
          gl_PointSize=a_Attr.z;
          v_Alpha=a_Attr.w;
      }
    </script>
    <!-- 片元着色器 -->
    <script id="fragmentShader" type="x-shader/x-fragment">
      precision mediump float;
      varying float v_Alpha;

      void main(){
        float dist=distance(gl_PointCoord,vec2(0.5,0.5));
        if(dist<0.5){
          gl_FragColor=vec4(0.87,0.91,1,v_Alpha);
        }else{
          discard;
        }
      }
    </script>
    <script type="module">
      import {
        initShaders,
        getMousePosInWebgl,
        glToCssPos,
      } from '../jsm/Utils.js'
      import Poly from '../jsm/Poly.js'
      import Sky from '../jsm/Sky.js'
      import Compose from '../jsm/Compose.js'
      import Track from '../jsm/Track.js'

      const canvas = document.querySelector('#canvas')
      canvas.width = window.innerWidth
      canvas.height = window.innerHeight

      // 获取着色器文本
      const vsSource = document.querySelector('#vertexShader').innerText
      const fsSource = document.querySelector('#fragmentShader').innerText

      //三维画笔
      const gl = canvas.getContext('webgl')
      gl.enable(gl.BLEND)
      gl.blendFunc(gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA)

      //初始化着色器
      initShaders(gl, vsSource, fsSource)

      //声明颜色 rgba
      gl.clearColor(0, 0, 0, 0)
      //刷底色
      gl.clear(gl.COLOR_BUFFER_BIT)

      //夜空
      const sky = new Sky(gl)

      // 建立合成对象
      const compose = new Compose()

      //正在绘制的多边形
      let poly = null

      // 鼠标正在经过的点
      let point = null

      canvas.oncontextmenu = function () {
        return false
      }

      canvas.addEventListener('mousedown', (event) => {
        if (event.button === 2) {
          popVertice()
        } else {
          const { x, y } = getMousePosInWebgl(event, canvas)
          if (poly) {
            addVertice(x, y)
          } else {
            // 建立多边形
            crtPoly(x, y)
          }
        }
        render()
      })

      canvas.addEventListener('mousemove', (event) => {
        if (poly) {
          const { x, y } = getMousePosInWebgl(event, canvas)
          point = hoverPoint(x, y)
          if (point) {
            canvas.style.cursor = 'pointer'
          } else {
            canvas.style.cursor = 'default'
          }
          if (poly) {
            const obj = poly.geoData[poly.geoData.length - 1]
            obj.x = x
            obj.y = y
          }
        }
      })

      function crtPoly(x, y) {
        const o1 = point ? point : { x, y, pointSize: random(), alpha: 1 }
        const o2 = { x, y, pointSize: random(), alpha: 1 }
        poly = new Poly({
          size: 4,
          attrName: 'a_Attr',
          geoData: [o1, o2],
          types: ['POINTS', 'LINE_STRIP'],
        })
        sky.add(poly)
        crtTrack(o1)
        crtTrack(o2)
      }

      function addVertice(x, y) {
        const { geoData } = poly
        if (point) {
          geoData[geoData.length - 1] = point
        }

        const obj = { x, y, pointSize: random(), alpha: 1 }
        geoData.push(obj)
        crtTrack(obj)
      }

      function crtTrack(obj) {
        const { pointSize } = obj
        const track = new Track(obj)
        track.start = new Date()
        track.timeLen = 2000
        track.loop = true
        track.keyMap = new Map([
          [
            'pointSize',
            [
              [500, pointSize],
              [1000, 0],
              [1500, pointSize],
            ],
          ],
          [
            'alpha',
            [
              [500, 1],
              [1000, 0],
              [1500, 1],
            ],
          ],
        ])

        compose.add(track)
      }

      function popVertice() {
        poly.geoData.pop()
        const { children } = compose
        const last = children[children.length - 1]
        children.delete(last)
        poly = null
      }

      function hoverPoint(mx, my) {
        for (let { geoData } of sky.children) {
          for (let obj of geoData) {
            if (poly && obj === poly.geoData[poly.geoData.length - 1]) {
              continue
            }

            const delta = {
              x: mx - obj.x,
              y: my - obj.y,
            }
            const { x, y } = glToCssPos(delta, canvas)
            const dist = x * x + y * y
            if (dist < 100) {
              return obj
            }
          }
        }
        return null
      }

      function render() {
        gl.clear(gl.COLOR_BUFFER_BIT)
        sky.draw()
      }

      function random() {
        return Math.random() * 8 + 3
      }

      !(function ani() {
        compose.update(new Date())
        sky.updateVertices(['x', 'y', 'pointSize', 'alpha'])
        render()
        requestAnimationFrame(ani)
      })()
    </script>
  </body>
</html>
